/**
 * 
 */
package cz.jarec.sender;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;

import cz.jarec.sender.exception.InvalidPhoneNumberException;
import cz.jarec.sender.exception.SenderInternalException;

/**
 * @author jarec
 * 
 */
public class SenderImpl implements Sender {

	private String portalUrl;
	private String username;
	private String password;

	private HtmlUnitDriver driver;

	/*
	 * (non-Javadoc)
	 * 
	 * @see cz.jarec.sender.Sender#sendSms(java.lang.String, java.lang.String)
	 */
	public void sendSms(String number, String text)
			throws InvalidPhoneNumberException, SenderInternalException {

		validatePhoneNumber(number);

		try {
			setupDriver();

			login();

			navigateToSms();

			sendSMS(number, text);
		} catch (Exception e) {
			throw new SenderInternalException(e);
		} finally {
			shutdown();
		}

	}

	/**
	 * 
	 */
	private void shutdown() {
		try {
			driver.quit();

			driver = null;
		} catch (Exception e) {
			// do nothing
		}

	}

	/**
	 * @param driver
	 */
	private void sendSMS(String num, String text) {

		driver.switchTo().defaultContent();

		WebElement frame = driver
				.findElement(By.xpath("//frame[@name='data']"));

		driver.switchTo().frame(frame);

		WebElement phoneNumber = driver.findElement(By.name("phoneNumber"));

		phoneNumber.sendKeys(num);

		WebElement textElement = driver.findElement(By.name("messageText"));

		textElement.sendKeys(text);

		WebElement sendButton = driver.findElement(By.name("akce"));

		sendButton.submit();
	}

	/**
	 * @param driver
	 */
	private void navigateToSms() {

		driver.switchTo().frame(0);

		WebElement menuElement = driver.findElement(By.id("link17"));

		menuElement.click();

	}

	/**
	 * @return
	 */
	private void setupDriver() {

		HtmlUnitDriver htmlDriver = new HtmlUnitDriver(true);

		htmlDriver.get(portalUrl);

		htmlDriver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

		driver = htmlDriver;
	}

	/**
	 * @param driver
	 */
	private void login() {

		WebElement usernameField = driver.findElement(By.name("username"));

		usernameField.sendKeys(username);

		WebElement passwordField = driver.findElement(By.name("password"));

		passwordField.sendKeys(password);

		WebElement submitButton = driver.findElement(By.name("login"));

		submitButton.click();
	}

	/**
	 * 
	 * @param string
	 * @throws InvalidPhoneNumberException
	 */
	private static void validatePhoneNumber(String string)
			throws InvalidPhoneNumberException {
		if (string.length() == 9) {
			validateNumber(string);
		} else if (string.length() == 13 && string.startsWith("+420")) {
			validateNumber(string.substring(4));
		} else {
			throw new InvalidPhoneNumberException(string);
		}

	}

	/**
	 * 
	 * @param string
	 * @throws InvalidPhoneNumberException
	 */
	private static void validateNumber(String string)
			throws InvalidPhoneNumberException {
		for (int i = 0; i < string.length(); i++) {
			if (!Character.isDigit(string.charAt(i))) {
				throw new InvalidPhoneNumberException(string);
			}
		}

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see cz.jarec.sender.Sender#getPortalUrl()
	 */
	public String getPortalUrl() {
		return portalUrl;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see cz.jarec.sender.Sender#setPortalUrl(java.lang.String)
	 */
	public void setPortalUrl(String portalUrl) {
		this.portalUrl = portalUrl;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see cz.jarec.sender.Sender#getUsername()
	 */
	public String getUsername() {
		return username;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see cz.jarec.sender.Sender#setUsername(java.lang.String)
	 */
	public void setUsername(String username) {
		this.username = username;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see cz.jarec.sender.Sender#getPassword()
	 */
	public String getPassword() {
		return password;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see cz.jarec.sender.Sender#setPassword(java.lang.String)
	 */
	public void setPassword(String password) {
		this.password = password;
	}

}
